package com.wjbgn.bsolver.server.scheduler.xxljob;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSONObject;
import com.wjbgn.bsolver.server.dto.BugAnsweredRecordDTO;
import com.wjbgn.bsolver.server.entity.BugAnswerAcceptRejectDO;
import com.wjbgn.bsolver.server.mapper.BugAnswerAcceptRejectMapper;
import com.wjbgn.stater.util.redis.RedisUtil;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 数据同步调度任务
 *
 * @author wjbgn
 * @date 2022/05/16 12:12
 **/
@Slf4j
@Component
public class DataSynchronizedJob {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private BugAnswerAcceptRejectMapper bugAnswerAcceptRejectMapper;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @XxlJob("updateAcceptRejectNumJob")
    public void updateAcceptRejectNumJob() {
        log.info("xxl job start !!!");
        // 更新数量
        Set<Object> set = redisUtil.getSetValue("answered:num:" + DateUtil.format(LocalDateTime.now().plusDays(0), "yyyy-MM-dd"));
        set.forEach(answeredId -> {
            long acceptNum = redisUtil.bitCount("answered:accept:" + answeredId) == null ? 0
                    : redisUtil.bitCount("answered:accept:" + answeredId);
            long rejectNum = redisUtil.bitCount("answered:reject:" + answeredId) == null ? 0
                    : redisUtil.bitCount("answered:reject:" + answeredId);

            // 更新数量
            Map<String, Integer> map = new HashMap<>();
            map.put("acceptNum", (int) acceptNum);
            map.put("rejectNum", (int) rejectNum);
            UpdateRequest updateNum = new UpdateRequest("bsolver_bug_answered_record", answeredId.toString())
                    .doc(JSONObject.toJSONString(map), XContentType.JSON);
            try {
                restHighLevelClient.update(updateNum, RequestOptions.DEFAULT);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        redisUtil.deleteObject("answered:num:" + DateUtil.format(LocalDateTime.now().plusDays(0), "yyyy-MM-dd"));
    }

    @XxlJob("updateUserAcceptRejectJob")
    public void updateUserAcceptRejectJob() {
        // 更新个人采纳无用数据
        for (; ; ) {
            Object o = redisUtil.rightPop("answered:user:" + DateUtil.format(LocalDateTime.now().plusDays(0), "yyyy-MM-dd"));
            if (null == o) {
                return;
            } else {
                BugAnsweredRecordDTO bugAnsweredRecordDTO = JSONObject.parseObject(JSONObject.toJSONString(o)).toJavaObject(BugAnsweredRecordDTO.class);
                this.updateAcceptRejectToEs(bugAnsweredRecordDTO);
            }
        }
    }

    /**
     * 持久化采纳和无用到es
     *
     * @param bugAnsweredRecordDTO
     * @author weirx
     * @date: 2022/5/16
     */
    public void updateAcceptRejectToEs(BugAnsweredRecordDTO bugAnsweredRecordDTO) {
        // 获取当前用户针对当前回复的采纳或点赞记录
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("bsolver_bug_answer_accept_reject");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        //各种查询
        queryBuilder.must(QueryBuilders.termQuery("answerId", bugAnsweredRecordDTO.getId()))
                .must(QueryBuilders.termQuery("username", bugAnsweredRecordDTO.getUsername()));
        sourceBuilder.query(queryBuilder);
        searchRequest.source(sourceBuilder);
        SearchResponse rp = null;
        try {
            rp = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        } catch (IOException e) {
            e.printStackTrace();
        }
        if (rp.getHits().getTotalHits().value > 0) {
            String id = null;
            for (SearchHit searchHit : rp.getHits()) {
                id = searchHit.getId();
            }
            // 更新记录表
            BugAnswerAcceptRejectDO bugAnswerAcceptRejectDO = new BugAnswerAcceptRejectDO(
                    bugAnsweredRecordDTO.isCurrentHasAccept() ? 1 : 0, bugAnsweredRecordDTO.isCurrentHasReject() ? 1 : 0);
            UpdateRequest updateRequest = new UpdateRequest("bsolver_bug_answer_accept_reject", id)
                    .doc(JSONObject.toJSONString(bugAnswerAcceptRejectDO), XContentType.JSON);
            try {
                restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            // 没有就直接保存
            bugAnswerAcceptRejectMapper.save(new BugAnswerAcceptRejectDO(
                    bugAnsweredRecordDTO.getId(),
                    bugAnsweredRecordDTO.getBugId(),
                    bugAnsweredRecordDTO.getUsername(),
                    bugAnsweredRecordDTO.getFlag().equals("accept") ? 1 : 0,
                    bugAnsweredRecordDTO.getFlag().equals("reject") ? 1 : 0,
                    LocalDateTimeUtil.now()
            ));
        }
    }
}
